import { Component, computed, DefineComponent, defineComponent, ExtractPropTypes, FunctionalComponent, nextTick, onMounted, PropType, ref, StyleValue, toRef, VNodeChild } from 'vue'
import { formatLength } from '../_util/css'
import { getComponent, getEL, _cloneVNode } from '../_util/props-util'
import { useMergedState } from '../_util/hooks'
import DragResize from '../drag-resize'
import Icon from '../icon'

const windowProps = {
  title: [String, Object] as PropType<VNodeChild>,
  prefix: [String, Object] as PropType<VNodeChild>,
  suffix: [String, Object] as PropType<VNodeChild>,
  draggable: { type: Boolean, default: true },
  closable: { type: Boolean, default: true },
  fullscreen: { type: Boolean, default: undefined },
  resizable: { type: Boolean, default: true },
  w: Number,
  h: Number,
  type: { type: String as PropType<'default' | 'simple'>, default: 'default' },
  headerStyle: [String, Array, Object] as PropType<StyleValue>,
  bodyStyle: [String, Array, Object] as PropType<StyleValue>,
  footer: [Function, Object, Array] as PropType<FunctionalComponent | DefineComponent | Component>
}

export type WindowProps = ExtractPropTypes<typeof windowProps>

const prefixCls = 'x-window'

export default defineComponent({
  name: prefixCls,
  props: windowProps,
  // prettier-ignore
  emits: [
    'close', 'resize',
    'dragging', 'resizing',
    'update:width', 'update:height',
    'update:x', 'update:y', 'update:w', 'update:h',
    'update:fullscreen',
    'resizing', 'resize-start', 'resize-end',
    'activated', 'deactivated',
  ],
  setup(props, { emit, slots }) {
    const elRef = ref<HTMLElement>()
    const headerRef = ref<HTMLElement>()

    // mousedown 触发聚焦
    onMounted(() => {
      getEL(elRef.value).addEventListener('mousedown', e => getEL(elRef.value).focus())
    })

    // ========================== fullscreen ==========================
    const mergeFullscreen = useMergedState(toRef(props, 'fullscreen'), ref(false), val => emit('update:fullscreen', val))
    const styleRef = computed(() => {
      return mergeFullscreen.value ? `` : `width: ${formatLength(props.h)}; height: ${formatLength(props.w)}`
    })

    let lastStyle = ''
    let style = ''
    function onToggleSize() {
      if (!props.resizable) return
      if (!mergeFullscreen.value) {
        // 全屏前保存 style
        lastStyle = getEL(elRef.value).getAttribute('style')
      } else {
        // 退出全屏恢复 style
        style = lastStyle
        nextTick(() => (style = ''))
      }
      mergeFullscreen.value = !mergeFullscreen.value
    }

    // ========================== event ==========================
    function onClose() {
      emit('close')
    }
    function prevent(e: Event) {
      e.stopPropagation()
      // e.preventDefault()
    }

    // prettier-ignore
    return vm => {
       return (
        <DragResize
          class={[prefixCls, `${prefixCls}-${props.type}`, {
            [`${prefixCls}-resizable`]: props.resizable,
            [`${prefixCls}-fullscreen`]: mergeFullscreen.value
          }]}
          style={style}
          ref={elRef}
          dragTarget={headerRef}
          type='simple'
          tabindex='0'
        >
          <div class={`${prefixCls}_header`} style={props.headerStyle} ref={headerRef}>
            {getComponent(vm, 'prefix')}
            <div class={`${prefixCls}_title`}>{getComponent(vm, 'title')}</div>
            <div class={`${prefixCls}_suffix`}>{getComponent(vm, 'suffix')}</div>
            {props.resizable && <Icon class={`${prefixCls}_operation`} type="Rectangle" onMousedown={prevent} onClick={onToggleSize} />}
            {props.closable && <Icon class={`${prefixCls}_operation ${prefixCls}_close`} type="cross" onMousedown={prevent} onClick={onClose} />}
          </div>
          <div class={`${prefixCls}_body`} style={props.bodyStyle}>
            {slots.default?.()}
          </div>
          {_cloneVNode(getComponent(vm, 'footer'), { class: `${prefixCls}_footer` })}
        </DragResize>
       )
    }
  }
})
